home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 7
/
Amiga Format AFCD07 (Dec 1996, Issue 91).iso
/
serious
/
shareware
/
comms
/
internet
/
html-related
/
hsc
/
source
/
hsclib
/
parse.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-31
|
31KB
|
1,099 lines
/*
* hsclib/parse.c
*
* parse file: handle for entities & tags
*
* Copyright (C) 1995,96 Thomas Aglassinger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* updated: 31-Aug-1996
* created: 1-Jul-1995
*
*/
#define NOEXTERN_HSCLIB_PARSE_H
#include "hsclib/inc_base.h"
#include "hsclib/defattr.h"
#include "hsclib/deftag.h"
#include "hsclib/idref.h"
#include "hsclib/include.h"
#include "hsclib/input.h"
#include "hsclib/parse.h"
#include "hsclib/posteval.h"
#include "hscprj/project.h"
#include "hsclib/skip.h"
#include "hsclib/size.h"
#include "hsclib/uri.h"
/*
*---------------------------
* misc. functions
*---------------------------
*/
/*
* message_rplc
*
* message that tells user that a special char
* was replaced by its entity
*/
static VOID message_rplc(HSCPRC * hp, STRPTR what, STRPTR by)
{
hsc_message(hp, MSG_RPLC_ENT,
"replaced %q by %q", what, by);
}
/*
* check_mbinaw
*
* check if tag occures at a allowed position
*/
static BOOL check_mbinaw(HSCPRC * hp, HSCTAG * tag)
{
BOOL ok = TRUE;
/* check for tags that must be called before */
if (tag->mbi)
{
DLNODE *nd = hp->container_stack->first;
LONG found = 0;
while (nd && !found)
{
HSCTAG *ctag = (HSCTAG *) nd->data;
found = strenum(ctag->name, tag->mbi, '|', STEN_NOCASE);
nd = nd->next;
}
if (!found)
{
hsc_message(hp, MSG_MBI,
"%T must be inside %t", tag, tag->mbi);
ok = FALSE;
}
}
/* check for tags that are not to be called before */
if (tag->naw)
{
DLNODE *nd = hp->container_stack->first;
LONG found = 0;
while (nd)
{
HSCTAG *ctag = (HSCTAG *) nd->data;
found = strenum(ctag->name, tag->naw, '|', STEN_NOCASE);
if (found)
{
hsc_message(hp, MSG_NAW,
"%T not allowed within %C", tag, ctag);
ok = FALSE;
}
nd = nd->next;
}
}
return (ok);
}
/* enable output for a process */
static void hp_enable_output(HSCPRC * hp, STRPTR cause)
{
if (hp->suppress_output)
{
D(fprintf(stderr, DHL "output enabled (%s)\n", cause));
}
hp->suppress_output = FALSE;
}
/*
*---------------------------
* remove/append end tag
* from/to container_stack
*---------------------------
*/
/*
* app_ctag
*
* create end tag and append it to tag-list;
* also clone options & attribute list of parent
* tag, if tag is a macro and has a closing tag.
*
* params: hp.....hscprc with container_stack to be modified
* tagid..name of the new tag (eg "IMG")
* result: ptr to the new tag or NULL if no mem
*/
HSCTAG *app_ctag(HSCPRC * hp, HSCTAG * tag)
{
HSCTAG *ctag;
DLLIST *taglist = hp->container_stack;
ctag = new_hsctag(tag->name);
if (ctag)
{
BOOL ok = TRUE;
DLNODE *nd = NULL;
/* copy important data of tag */
ctag->option = tag->option;
/* clone attributes, if tag is a
* macro tag and has a closing tag
*/
if ((tag->option & HT_MACRO)
&& (tag->option & HT_CLOSE))
{
ok = copy_local_varlist(
ctag->attr, tag->attr, MCI_APPCTAG);
}
/* remeber position where start tag has been called */
/* (for message "end tag missing) */
ctag->start_fpos = new_infilepos(hp->inpf);
/* insert tag in list */
if (ok)
{
nd = app_dlnode(taglist, ctag);
if (!nd)
{
del_hsctag((APTR) ctag);
ctag = NULL;
}
}
}
return (ctag);
}
/*
* params: tagname..tag to remove
* check....show messages
*/
VOID remove_ctag(HSCPRC * hp, HSCTAG * tag)
{
/* search for tag on stack of occured tags */
DLNODE *nd = find_dlnode(hp->container_stack->first, (APTR) tag->name, cmp_strtag);
if (nd == NULL)
{
/* closing tag not found on stack */
/* ->unmatched closing tag without previous opening tag */
if (!(tag->option & HT_AUTOCLOSE))
hsc_message(hp, MSG_UNMA_CTAG, "unmatched %C ", tag);
}
else
{
/* closing tag found on stack */
HSCTAG *ctag = (HSCTAG *) nd->data;
STRPTR foundnm = (STRPTR) ctag->name;
STRPTR lastnm = (STRPTR) hp->container_stack->last->data;
/* check if name of closing tag is -not- equal
* to the name of the last tag last on stack
* ->illegal tag nesting
*/
if (upstrcmp(lastnm, foundnm)
&& !(tag->option | HT_MACRO)
&& !(is_hsc_tag(tag)))
{
hsc_message(hp, MSG_CTAG_NESTING,
"illegal end tag nesting (expected %c, found %C)",
lastnm, tag);
}
/* if closing tag has any attributes defined,
* it must be a closing macto tag. so copy
* the attributes of the closing tag to the
* attributes of the macro tag. therefor,
* the closing macro tag inherits the
* attributes of his opening macro
*/
if (ctag->attr)
set_local_varlist(tag->attr, ctag->attr, MCI_APPCTAG);
/* remove node for closing tag from container_stack */
del_dlnode(hp->container_stack, nd);
}
}
/*
*---------------------------
* parse tag functions
*---------------------------
*/
/*
* hsc_parse_tag
*
* parse tag (after "<")
*/
BOOL hsc_parse_tag(HSCPRC * hp)
{
INFILE *inpf = hp->inpf;
STRPTR nxtwd = NULL;
DLNODE *nd = NULL;
HSCTAG *tag = NULL;
ULONG tci = 0; /* tag_call_id returned by set_tag_args() */
BOOL(*hnd) (HSCPRC * hp, HSCTAG * tag) = NULL;
BOOL open_tag;
DLLIST *taglist = hp->deftag;
BOOL rplc_lt = FALSE; /* TRUE, if replace spc. char "<" */
BOOL hnd_result = TRUE; /* result returned by handle */
BOOL unknown_tag = FALSE; /* TRUE, if tag has not been defined before */
/* init strings used inside tag-handles */
set_estr(hp->tag_name_str, infgetcw(inpf));
clr_estr(hp->tag_attr_str);
clr_estr(hp->tag_close_str);
if (hp->smart_ent && strlen(infgetcws(inpf)))
{
/*
* check for special char "<"
*/
int ch = infgetc(inpf);
if (hsc_whtspc(ch))
{
rplc_lt = TRUE;
/* write "<" and white spaces */
message_rplc(hp, "<", "<");
hsc_output_text(hp, infgetcws(inpf), "<");
}
inungetc(ch, inpf);
}
if (!rplc_lt)
{
/* get tag id */
nxtwd = infget_tagid(hp);
if (!hp->fatal)
{
/* append tag-name to tag_name_str */
app_estr(hp->tag_name_str, infgetcws(inpf));
app_estr(hp->tag_name_str, infgetcw(inpf));
/* check for hsctag; if not, enable output */
if (hp->suppress_output
&& upstrncmp(nxtwd, HSC_TAGID, strlen(HSC_TAGID))
&& strcmp(nxtwd, HSC_COMMENT_STR)
&& strcmp(nxtwd, HSC_ONLYCOPY_STR)
)
{
hp_enable_output(hp, "non-hsctag occured");
}
if (!hp->suppress_output)
{
D(fprintf(stderr, DHL "tag <"));
}
}
}
if (!hp->fatal && !rplc_lt)
{
BOOL write_tag = FALSE; /* flag: write tag text & attrs to output? */
if (strcmp("/", nxtwd)) /* is it a closing tag? */
{
/*
*
* process start-tag
*
*/
open_tag = TRUE;
if (!hp->suppress_output)
{
D(fprintf(stderr, "%s>\n", nxtwd));
}
/* search for tag in list */
nd = find_dlnode(taglist->first, (APTR) nxtwd, cmp_strtag);
if (nd == NULL)
{
hsc_message(hp, MSG_UNKN_TAG, /* tag not found */
"unknown %t", nxtwd);
tag = new_hsctag(nxtwd);
tag->option |= HT_UNKNOWN;
unknown_tag = TRUE;
#if 0
/* NOTE: This one's a bit perverted, because
* the closing ">" is appended to the
* attribute string, and the closing string
* is left empty; as there is nearly no code
* between setting and writing the strings,
* I think this is more reasonable than doing
* some tricky string-manipulation...
*/
skip_until_eot(hp, hp->tag_attr_str);
clr_estr(hp->tag_close_str);
#endif
}
else
{
tag = (HSCTAG *) nd->data;
}
/* set handle-function */
hnd = tag->o_handle;
/*
* handle options
*/
/* check for obsolete tag */
if (tag->option & HT_OBSOLETE)
{
hsc_message(hp, MSG_TAG_OBSOLETE,
"%T is obsolete", tag);
}
/* check for jerk-tag */
if (tag->option & HT_JERK)
{
hsc_message(hp, MSG_TAG_JERK,
"%T is only used by jerks", tag);
}
/* only-once-tag occured twice? */
if ((tag->option & HT_ONLYONCE) && (tag->occured))
{
hsc_message(hp, MSG_TAG_TOO_OFTEN,
"%T occured too often", tag);
}
/* set occured-flag */
if (tag->option & (HT_ONLYONCE | HT_REQUIRED))
tag->occured = TRUE;
/* check for "must be inside"/"not allowed within"-tags */
if (!check_mbinaw(hp, tag))
hnd = NULL;
/* clear (reset to default) attribute values of tag */
clr_varlist(tag->attr);
/* set attributes or check for ">" */
if (!(tag->option & HT_SPECIAL))
{
tci = set_tag_args(hp, tag);
if (tci == MCI_ERROR)
{
skip_until_eot(hp, NULL);
hnd = NULL;
}
if (!hp->fatal)
{
/* set ">" in string that contains closing text */
set_estr(hp->tag_close_str, infgetcws(inpf));
set_estr(hp->tag_close_str, infgetcw(inpf));
/* check for succeeding white-space */
if ((tag->option & HT_WHTSPC)
&& !infeof(inpf))
{
int ch = infgetc(inpf);
if ((ch == ' ')
|| (ch == '\n')
|| (ch == '\t'))
{
hsc_message(hp, MSG_SUCC_WHTSPC,
"succeeding white-space for %T",
tag);
}
inungetc(ch, inpf);
}
}
}
/* end-tag required? */
if (tag->option & HT_CLOSE)
app_ctag(hp, tag);
}
else
{
/*
*
* process end-tag
*
*/
/* get tag id */
nxtwd = infget_tagid(hp); /* get tag id */
open_tag = FALSE;
/* append tag-name to tag_name_str */
app_estr(hp->tag_name_str, infgetcws(inpf));
app_estr(hp->tag_name_str, infgetcw(inpf));
if (!hp->suppress_output)
{
D(fprintf(stderr, "/%s>\n", nxtwd));
}
/* search for tag in taglist */
/* (see if it exists at all) */
nd = find_dlnode(taglist->first, (APTR) nxtwd, cmp_strtag);
if (nd == NULL)
{
/* closing tag is absolutely unknown */
hsc_message(hp, MSG_UNKN_TAG, /* tag not found */
"unknown %c", nxtwd);
skip_until_eot(hp, hp->tag_attr_str);
}
else
{
tag = (HSCTAG *) nd->data; /* fitting tag in taglist */
/* check for preceding white-spaces */
if ((tag->option & HT_WHTSPC) && hp->preceding_whtspc)
{
hsc_message(hp, MSG_PREC_WHTSPC,
"preceding white-space for %C",
tag);
}
if (tag->option & (HT_CLOSE | HT_AUTOCLOSE))
{
/* set closing handle */
hnd = tag->c_handle;
/* check for no args */
if (!parse_wd(hp, ">"))
{
hsc_message(hp, MSG_CL_TAG_ARG,
"no attributes allowed for end-tags");
}
else
{
/* set ">" in string that contains closing text */
set_estr(hp->tag_close_str, infgetcws(inpf));
app_estr(hp->tag_close_str, infgetcw(inpf));
}
/* set values of attributes stored
* in end-tag,
* remove end-tag from stack
*/
remove_ctag(hp, tag);
}
else
{
/* illegal closing tag */
hsc_message(hp, MSG_ILLG_CTAG, /* tag not found */
"illegal %c", nxtwd);
parse_gt(hp);
tag = NULL;
}
}
}
/*
* processed for opening AND closing tag
*/
write_tag = (!(tag) || !(tag->option & HT_NOCOPY));
if (tag)
{
/*
* check if tag should be stripped
*/
if (!postprocess_tagattr(hp, tag, open_tag))
{
/* stripped tag with external reference */
if (open_tag)
hsc_msg_stripped_tag(hp, tag, "external reference");
hnd = NULL; /* don't call handle */
write_tag = FALSE; /* don't output tag */
}
else if (hp->strip_tags
&& strenum(tag->name, hp->strip_tags, '|', STEN_NOCASE))
{
/* strip tag requested by user */
if (!(tag->option & HT_SPECIAL))
{
if (open_tag)
hsc_msg_stripped_tag(hp, tag, "as requested");
hnd = NULL; /* don't call handle */
write_tag = FALSE; /* don't output tag */
}
else
{
hsc_message(hp, MSG_TAG_CANT_STRIP,
"can't strip special tag %T", tag);
}
/*
* get values for size from reference
*/
}
else if (tag->uri_size && get_vartext(tag->uri_size))
get_attr_size(hp, tag);
}
/* call handle if available */
if (hnd && !hp->fatal)
hnd_result = (*hnd) (hp, tag);
/* write whole tag out */
if (write_tag && hnd_result)
{
VOID(*tag_callback) (struct hscprocess * hp,
HSCTAG * tag,
STRPTR tag_name, STRPTR tag_attr, STRPTR tag_close) = NULL;
if (open_tag)
tag_callback = hp->CB_start_tag;
else
tag_callback = hp->CB_end_tag;
if (tag_callback)
{
(*tag_callback) (hp, tag,
estr2str(hp->tag_name_str),
estr2str(hp->tag_attr_str),
estr2str(hp->tag_close_str));
}
}
/* skip LF if requested */
if (tag && (tag->option & HT_SKIPLF))
skip_lf(hp);
/* remove temporary created tag */
if (unknown_tag)
del_hsctag(tag);
}
return (BOOL) (!hp->fatal);
}
/*
*---------------------------
* other parse functions
*---------------------------
*/
/* replace icon-entity by image */
static VOID replace_icon(HSCPRC * hp, STRPTR icon)
{
INFILEPOS *base = new_infilepos(hp->inpf);
EXPSTR *image = init_estr(0);
/* create string like <IMG SRC=":icons/back.gif" ALT="back"> */
set_estr(image, "<IMG SRC=\"");
estrcat(image, hp->iconbase);
/* check, if iconbase contains "*" */
if (strchr(estr2str(hp->iconbase), '*'))
{
STRPTR s = estr2str(hp->iconbase);
while(s[0])
{
if (s[0] =='*')
app_estr(image, icon);
else
app_estrch(image, s[0]);
s++;
}
}
else
{
app_estr(image, icon);
app_estr(image, ".gif");
}
app_estr(image, "\" ALT=\"");
app_estr(image, icon);
app_estr(image, "\">");
hsc_message(hp, MSG_RPLC_ICON, "replacing icon-%e", icon);
hsc_include_string(hp, SPECIAL_FILE_ID "include icon",
estr2str(image),
IH_PARSE_HSC | IH_NO_STATUS | IH_POS_PARENT);
del_estr(image);
del_infilepos(base);
}
/*
* hsc_parse_amp
*
* parse ampersand ("&")
*/
BOOL hsc_parse_amp(HSCPRC * hp)
{
INFILE *inpf = hp->inpf;
EXPSTR *amp_str = init_estr(0);
if (!hp->fatal)
{
BOOL rplc = hp->smart_ent; /* TRUE, if "&" should be replaced */
hp_enable_output(hp, "entity");
if (rplc)
{
/*
* test if char before and
* after ">" is white-space
*/
int ch = infgetc(inpf);
inungetc(ch, inpf);
if (!(hsc_whtspc(ch) && strlen(infgetcws(inpf))))
rplc = FALSE;
}
if (rplc)
{
/* replace ampersand */
message_rplc(hp, "&", "&");
set_estr(amp_str, "&");
}
else
{
/*
* get entity-id, test for unknown entity
*/
char *nxtwd;
DLNODE *nd;
BOOL app_entity = TRUE;
/* remember "&" */
set_estr(amp_str, infgetcw(inpf));
/* get entity id */
nxtwd = infgetw(inpf);
/* TODO: check for white-space */
if (!strcmp(nxtwd, "#"))
{
/*
* process numeric entity
*/
/* append "#" */
app_estr(amp_str, infgetcw(inpf));
nxtwd = infgetw(inpf);
errno = 0;
strtoul(nxtwd, NULL, 0);
if (errno || strlen(infgetcws(inpf)))
{
hsc_message(hp, MSG_ILLG_NUM, /* illegal numeric entity */
"illegal numeric value %n for entity", nxtwd);
}
/* append entity specifier */
app_estr(amp_str, nxtwd);
}
else
{
/*
* process text entity
*/
HSCVAR *attr = NULL;
/* search for entity in list */
nd = find_dlnode(hp->defent->first, (APTR) nxtwd, cmp_strent);
if (hp->jens && (nd == NULL))
{
/* asume that entity is an attribute,
* try to find it and append it's value
*/
attr = find_varname(hp->defattr, nxtwd);
if (attr)
{
set_estr(amp_str, get_vartext(attr));
app_entity = FALSE;
}
}
if ((nd == NULL) && (attr == NULL))
{
hsc_message(hp, MSG_UNKN_ENTITY,
"unknown %e", nxtwd);
}
else
{
/* check for icon-entity and warn about */
/* portability peoblem */
HSCENT *entity = dln_data(nd);
if (entity->numeric == ICON_ENTITY)
if (estrlen(hp->iconbase))
{
replace_icon(hp, nxtwd);
set_estr(amp_str, "");
app_entity = FALSE;
}
else
{
hsc_message(hp, MSG_ICON_ENTITY,
"icon-%e found", nxtwd);
}
}
if (app_entity)
/* append entity specifier */
app_estr(amp_str, nxtwd);
}
/* TODO: check for whitespace before ";" */
/* check for closing ';' */
parse_wd(hp, ";");
/* append ";" */
if (app_entity)
app_estr(amp_str, infgetcw(inpf));
}
/* output whole entity */
if (estrlen(amp_str))
hsc_output_text(hp, "", estr2str(amp_str));
del_estr(amp_str);
}
return (BOOL) (!hp->fatal);
}
/*
* hsc_parse_text
*/
BOOL hsc_parse_text(HSCPRC * hp)
{
INFILE *inpf = hp->inpf;
STRPTR nw = infgetcw(inpf);
if (nw && hp->suppress_output && (strcmp(nw, "\n")))
hp_enable_output(hp, "non-LF text");
if (nw)
{ /* do test below only if not end-of-file */
/*
* check unmatched ">"
*/
if (!strcmp(nw, ">"))
{
BOOL rplc = hp->smart_ent; /* TRUE, if ">" should be replaced */
if (rplc)
{
/*
* test if char before and
* after ">" is white-space
*/
int ch = infgetc(inpf);
inungetc(ch, inpf);
if (!(hsc_whtspc(ch) && strlen(infgetcws(inpf))))
{
rplc = FALSE;
}
else
{
};
}
if (rplc)
{
/* replace gt */
message_rplc(hp, nw, ">");
nw = ">";
}
else
{
hsc_message(hp, MSG_UNMA_GT,
"unmatched \">\"");
}
}
/*
* check for quote
*/
else if (!strcmp(nw, "\""))
{
if (hp->rplc_quote)
{
/* replace quote */
message_rplc(hp, nw, """);
nw = """;
}
}
/*
* check for entities to replace
*/
else
{
DLNODE *nd = NULL; /* entity search result */
if (hp->rplc_ent && (strlen(nw) == 1) && (nw[0] >= 127))
{
nd = find_dlnode(hp->defent->first, (APTR) nw, cmp_rplcent);
if (nd)
{
BOOL ok = TRUE;
/* copy replaced entity to buffer */
ok &= set_estr(hp->tmpstr, "&");
ok &= app_estr(hp->tmpstr, ((HSCENT *) nd->data)->name);
ok &= app_estr(hp->tmpstr, ";");
if (ok)
{
/* replace-message */
message_rplc(hp, nw, estr2str(hp->tmpstr));
nw = estr2str(hp->tmpstr);
}
}
}
/*
* check for "click here" syndrome
*/
if (hp->inside_anchor && hp->click_here_str)
{
ULONG found = strenum(nw, hp->click_here_str, '|', STEN_NOCASE);
if (found)
{
hsc_message(hp, MSG_CLICK_HERE,
"`click here'-syndrome detected");
}
}
}
}
if (nw)
hsc_output_text(hp, "", nw); /* output word */
return (BOOL) (!hp->fatal);
}
/*
* hsc_parse
*
* parse input chars with full hsc support
*
* params: inpf...input file
*
* result: TRUE, if no error
*/
BOOL hsc_parse(HSCPRC * hp)
{
if (!hp->fatal)
{
STRPTR nxtwd = infgetw(hp->inpf);
/*
* handle LineFeed: with COMPACT set, write LF without
* any WhtSpcs and skip any following WhtSpcs. No
* further parsing on the current word will be done.
*/
if (nxtwd && (!strcmp(nxtwd, "\n")))
{
BOOL suppress_lf = FALSE;
if (!(hp->inside_pre))
{
if (hp->compact)
{
/* write LF without WhtSpc */
hsc_output_text(hp, "", "\n");
/* skip all followings LFs */
skip_lfs(hp);
/* strip WhtSpcs of next word */
infskip_ws(hp->inpf);
suppress_lf = TRUE;
}
}
if (!suppress_lf)
{
/* write out LF with WhtSpcs */
hsc_output_text(hp, infgetcws(hp->inpf), nxtwd);
}
hp->preceding_whtspc = TRUE;
}
else
{
/* write white spaces */
STRPTR cws = infgetcws(hp->inpf); /* current WhtSpcs */
if (cws)
{
if (!(hp->compact) || (hp->inside_pre))
{
/* write all WhtSpcs */
hsc_output_text(hp, cws, "");
}
else if (strlen(cws))
{
/* write single WhtSpc */
hsc_output_text(hp, " ", "");
}
#if 0
else if (cws)
{
DMSG("no whitespaces to output (len=0)");
}
else
{
DMSG("no whitespaces to output (NULL)");
}
#endif
/* check for preceding white-spaces */
if (strlen(cws))
hp->preceding_whtspc = TRUE;
}
/* parse text */
if (nxtwd)
{
if (!strcmp(nxtwd, "<")) /* parse tag */
hsc_parse_tag(hp);
else if (!strcmp(nxtwd, "&")) /* parse entity */
hsc_parse_amp(hp);
else
{ /* handle text */
hsc_parse_text(hp);
}
}
hp->preceding_whtspc = FALSE;
}
}
return (BOOL) (!hp->fatal);
}
/*
* hsc_parse_source
*
* parse input chars with full hsc support
*
* params: inpf...input file
*
* result: TRUE, if no error
*/
BOOL hsc_parse_source(HSCPRC * hp)
{
if (!hp->fatal)
{
char *nxtwd = infgetw(hp->inpf);
if (nxtwd)
{
/*
* process next word
*/
if (!strcmp(nxtwd, "<"))
hsc_output_text(hp, infgetcws(hp->inpf), "<");
else if (!strcmp(nxtwd, ">"))
hsc_output_text(hp, infgetcws(hp->inpf), ">");
else if (!strcmp(nxtwd, "&"))
hsc_output_text(hp, infgetcws(hp->inpf), "&");
else
{
hsc_output_text(hp, infgetcws(hp->inpf), "");
hsc_parse_text(hp);
}
}
}
return (BOOL) (!hp->fatal);
}
/*
*---------------------------
* parse end functions
*---------------------------
*/
/*
* hsc_parse_end
*
* check for all tags closed and required
* tags occured
*/
BOOL hsc_parse_end(HSCPRC * hp)
{
if (!hp->fatal)
{
INFILEPOS *infpos = new_infilepos(hp->inpf);
/* check for unclosed containers */
DLNODE *nd = hp->container_stack->first;
while (nd)
{
HSCTAG *endtag = (HSCTAG *) dln_data(nd);
set_infilepos(hp->inpf, endtag->start_fpos);
hsc_message(hp, MSG_MISS_CTAG,
"%c missing", endtag->name);
nd = dln_next(nd);
}
set_infilepos(hp->inpf, infpos);
del_infilepos(infpos);
/* check for required tags missing */
nd = hp->deftag->first;
while (nd)
{
HSCTAG *tag = (HSCTAG *) nd->data;
if ((tag->option & HT_REQUIRED
&& (tag->occured == FALSE)))
{
hsc_message(hp, MSG_MISS_REQTAG,
"required %T missing", tag);
}
nd = nd->next;
}
}
return (BOOL) (!hp->fatal);
}
/*
*---------------------------
* parse IDs functions
*---------------------------
*/
/*
* hsc_parse_end_id
*
* append all locally defined IDs to global IDs,
* check all before referenced local IDs
*
*/
BOOL hsc_parse_end_id(HSCPRC * hp)
{
if (!hp->fatal)
check_all_local_idref(hp); /* check local IDs */
return (BOOL) (!hp->fatal);
}